import { JavascriptGenerator, javascriptGenerator } from "blockly/javascript";
import { Tanslate } from "./translate";
import * as Blockly from 'blockly/core';
import { getValue } from "./com";
export namespace Runtims {
    const blocks = [
        {
            'key': 'code_comment',
            'message0': '%{code_comment} %1',
            'args0': [
                {
                    'type': 'field_input',
                    'name': 'VALUE',
                    'text': 'Code Comment'
                },
            ],
            'message1': '%{code_block} %1',
            'args1': [
                {
                    'type': 'input_statement',
                    'name': 'DO0',
                },
            ],
            'previousStatement': null,
            'nextStatement': null,
            'colour': 45
        },
        {
            "key": "to_type_value",
            "message0": "%1 %{to} %2",
            "args0": [
                {
                    "type": "input_value",
                    "name": "VALUE",
                },
                {
                    'type': 'field_dropdown',
                    'name': 'TYPE',
                    'options': [
                        ['%{text}', 'String'],
                        ['%{number}', 'Number'],
                        ['%{boolean}', 'Boolean'],
                    ],
                },
            ],
            "output": ["String", "Number", "Boolean"],
            "colour": 200
        },
        {
            "key": "is_type_value",
            "message0": "%1 %{is} %2",
            "args0": [
                {
                    "type": "input_value",
                    "name": "VALUE",
                },
                {
                    'type': 'field_dropdown',
                    'name': 'TYPE',
                    'options': [
                        ['%{text}', 'string'],
                        ['%{number}', 'number'],
                        ['%{boolean}', 'boolean'],
                        ['%{object}', 'object'],
                        ['%{undefined}', 'undefined'],
                        ['%{function}', 'function'],
                    ],
                },
            ],
            "output": 'Boolean',
            "colour": 200
        },
        {
            "key": "value_is_empty",
            "message0": "%1 %{value_is_empty}",
            "args0": [
                {
                    "type": "input_value",
                    "name": "VALUE",
                }
            ],
            "output": 'Boolean',
            "colour": 200
        },
        {
            "key": "serialize_data",
            "message0": "%{serialize_data} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "value",
                    "check": ["Array", "Object"]
                }
            ],
            "output": "String",
            "colour": 200
        },
        {
            "key": "unserialize_data",
            "message0": "%{unserialize_data} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "value",
                    "check": "String"
                }
            ],
            "output": ["Array", "Object"],
            "colour": 200
        },
        {
            "key": "to_base64",
            "message0": "%{to_base64} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "value",
                    "check": "String"
                }
            ],
            "output": "String",
            "colour": 200
        },
        {
            "key": "from_base64",
            "message0": "%{from_base64} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "value",
                    "check": "String"
                }
            ],
            "output": "String",
            "colour": 200
        },
        {
            "key": "url_encode",
            "message0": "%{url_encode} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "value",
                    "check": "String"
                }
            ],
            "output": "String",
            "colour": 200
        },
        {
            "key": "url_decode",
            "message0": "%{url_decode} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "value",
                    "check": "String"
                }
            ],
            "output": "String",
            "colour": 200
        },
        {
            "key": "create_object",
            "message0": "%{create_object}",
            "nextStatement": null,
            "previousStatement": null,
            "output": "Object",
            "colour": 200
        },
        {
            "key": "get_object_property",
            "message0": "%{get_object_property} %1 %{property} %2",
            "args0": [
                {
                    "type": "input_value",
                    "name": "obj",
                    "check": "Object"
                },
                {
                    "type": "input_value",
                    "name": "key",
                    "check": "String"
                },
            ],
            "nextStatement": null,
            "previousStatement": null,
            "output": ["Number", "Object", "String", "Function"],
            "inputsInline": true,
            "colour": 200
        },
        {
            "key": "set_object_property",
            "message0": "%{set_object_property} %1 %{property} %2 %{value} %3",
            "args0": [
                {
                    "type": "input_value",
                    "name": "obj",
                    "check": "Object"
                },
                {
                    "type": "input_value",
                    "name": "key",
                    "check": "String"
                },
                {
                    "type": "input_value",
                    "name": "value"
                },
            ],
            "nextStatement": null,
            "previousStatement": null,
            "output": "String",
            "inputsInline": true,
            "colour": 200
        },
        {
            "key": "get_object_keys",
            "message0": "%{get_object_keys} %1",
            "args0": [
                {
                    "type": "input_value",
                    "name": "obj",
                    "check": "Object"
                }
            ],
            "output": "Array",
            "inputsInline": true,
            "colour": 200
        },
        {
            "key": "object_to_url",
            "message0": "%{from} %1 %{object_to_url}",
            "args0": [
                {
                    "type": "input_value",
                    "name": "OBJ",
                    "check": "Object"
                }
            ],
            "output": "String",
            "inputsInline": true,
            "colour": 200
        },
        {
            "key": "create_blob",
            "message0": "%{from} %1 %{create_blob} %2",
            "args0": [
                {
                    "type": "input_value",
                    "name": "VALUE",
                    "check": ['Array', 'Blob']
                },
                {
                    'type': 'field_dropdown',
                    'name': 'TYPE',
                    'options': [
                        ['text', 'text/plain'],
                        ['json', 'application/json'],
                        ['xml', 'application/xml'],
                        ['html', 'text/html'],
                        ['csv', 'text/csv'],
                        ['mp4', 'video/mp4'],
                        ['pdf', 'application/pdf'],
                        ['png', 'image/png'],
                        ['jpg', 'image/jpeg'],
                        ['gif', 'image/gif'],
                        ['bmp', 'image/bmp'],
                        ['ogg', 'audio/ogg'],
                    ],
                },
            ],
            "output": "Blob",
            "inputsInline": true,
            "tooltip": "%{blob_tips}",
            "colour": 200
        },
        {
            'key': 'try_catch',
            'message0': '%{try_do} \n %1',
            "args0": [
                {
                    'type': 'input_statement',
                    'name': 'BODY0',
                },
            ],
            "message1": "%{catch_do} %2 \n %1",
            "args1": [
                {
                    'type': 'input_statement',
                    'name': 'BODY1',
                },
                {
                    "type": "field_input",
                    "name": "ARG",
                    "text": "event"
                },
            ],
            "tooltip": "%{try_catch_tips}",
            "nextStatement": null,
            "previousStatement": null,
            'colour': 290
        },
    ]
    export function init() {
        initGenerator()
        Tanslate.tr(blocks).forEach((item: any) => {
            Blockly.Blocks[item.key] = {
                init: function (this: any) {
                    this.jsonInit(item);
                }
            }
        })
    }

    export function getTools() {
        const netBlocks = {
            kind: 'category',
            name: Blockly.Msg['runtimes'],
            'colour': 45,
            contents: [] as any[]
        }
        blocks.forEach((item: any) => {
            netBlocks.contents.push({
                kind: 'block',
                type: item.key
            })
        })

        return netBlocks
    }

    function initGenerator() {
        javascriptGenerator.forBlock['code_comment'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const body = block.getInputTargetBlock('DO0');
            let VALUE = getValue(block, generator, 'VALUE')
            let lines = ''
            if (body) {
                const line = generator.blockToCode(body)
                lines = (typeof line === 'string' ? line : line.join('\n'))
            }
            if (!VALUE) {
                VALUE = 'Code Comment'
            }
            return `\n/* ${VALUE}--start */\n${lines}\n/* ${VALUE}--end */\n`;
        }

        javascriptGenerator.forBlock['to_type_value'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE');
            const TYPE = getValue(block, generator, 'TYPE');
            if (!VALUE) {
                throw new Error(block.id);
            }
            return `${TYPE}(${VALUE})`;
        }

        javascriptGenerator.forBlock['is_type_value'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE');
            const TYPE = getValue(block, generator, 'TYPE');
            if (!VALUE) {
                throw new Error(block.id);
            }
            return `typeof(${VALUE}) === '${TYPE}'`;
        }

        javascriptGenerator.forBlock['value_is_empty'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE');
            if (!VALUE) {
                throw new Error(block.id);
            }
            return `(${VALUE} === ''||${VALUE} === undefined||${VALUE} === null||${VALUE} === []||${VALUE} === {})`;
        }

        javascriptGenerator.forBlock['serialize_data'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const value = getValue(block, generator, 'value');
            if (!value) {
                throw new Error(block.id);
            }
            return `JSON.stringify(${value})`;
        }

        javascriptGenerator.forBlock['unserialize_data'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const value = getValue(block, generator, 'value');
            if (!value) {
                throw new Error(block.id);
            }
            return `JSON.parse(${value})`;
        }

        javascriptGenerator.forBlock['to_base64'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const value = getValue(block, generator, 'value')?.trim();
            if (!value) {
                throw new Error(block.id);
            }
            return `btoa(${value})`;
        }

        javascriptGenerator.forBlock['from_base64'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const value = getValue(block, generator, 'value')?.trim();
            if (!value) {
                throw new Error(block.id);
            }
            return `atob(${value})`;
        }

        javascriptGenerator.forBlock['url_encode'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const value = getValue(block, generator, 'value')?.trim();
            if (!value) {
                throw new Error(block.id);
            }
            return `encodeURI(${value})`;
        }

        javascriptGenerator.forBlock['url_dncode'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const value = getValue(block, generator, 'value')?.trim();
            if (!value) {
                throw new Error(block.id);
            }
            return `decodeURI(${value})`;
        }

        javascriptGenerator.forBlock['create_object'] = function () {
            return `{}`;
        }

        javascriptGenerator.forBlock['get_object_property'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const obj = getValue(block, generator, 'obj')?.trim();
            const key = getValue(block, generator, 'key')?.trim();
            if (!obj || !key) {
                throw new Error(block.id);
            }
            return `Reflect.get(${obj},${key})`;
        }

        javascriptGenerator.forBlock['set_object_property'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const obj = getValue(block, generator, 'obj')?.trim();
            const key = getValue(block, generator, 'key')?.trim();
            const value = getValue(block, generator, 'value')?.trim();
            if (!obj || !key) {
                throw new Error(block.id);
            }
            return `${obj}["${key.replace(/["']/g, '')}"]=${value};\n`;
        }

        javascriptGenerator.forBlock['get_object_keys'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const obj = getValue(block, generator, 'obj')?.trim();
            if (!obj) {
                throw new Error(block.id);
            }
            return `Reflect.ownKeys(${obj})`;
        }

        javascriptGenerator.forBlock['set_timeout'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const body = block.getInputTargetBlock('DO0');
            const TIME = getValue(block, generator, 'TIME')
            let lines = ''
            if (body) {
                const line = generator.blockToCode(body)
                lines = (typeof line === 'string' ? line : line.join('\n'))
            }
            if (!TIME) {
                throw new Error(block.id);
            }
            if (block.outputConnection?.targetBlock()) {
                return `setTimeout(() => {\n${lines}\n}, ${TIME})`;
            }
            return `setTimeout(() => {\n${lines}\n}, ${TIME});\n`;
        }

        javascriptGenerator.forBlock['clear_timeout'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE')
            if (!VALUE) {
                throw new Error(block.id);
            }
            return `clearTimeout(${VALUE});`;
        }

        javascriptGenerator.forBlock['set_interval'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const body = block.getInputTargetBlock('DO0');
            const TIME = getValue(block, generator, 'TIME')
            let lines = ''
            if (body) {
                const line = generator.blockToCode(body)
                lines = (typeof line === 'string' ? line : line.join('\n'))
            }
            if (!TIME) {
                throw new Error(block.id);
            }
            if (block.outputConnection?.targetBlock()) {
                return `setInterval(() => {\n${lines}\n}, ${TIME})`;
            }
            return `setInterval(() => {\n${lines}\n}, ${TIME});`;
        }

        javascriptGenerator.forBlock['clear_interval'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE')
            if (!VALUE) {
                throw new Error(block.id);
            }
            return `clearInterval(${VALUE});`;
        }

        javascriptGenerator.forBlock['object_to_url'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const OBJ = getValue(block, generator, 'OBJ')
            if (!OBJ) {
                throw new Error(block.id);
            }
            return `URL.createObjectURL(${OBJ})`;
        }

        javascriptGenerator.forBlock['create_blob'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE')
            const TYPE = getValue(block, generator, 'TYPE')
            if (!VALUE) {
                throw new Error(block.id);
            }
            return `(new Blob(${VALUE}, {type: '${TYPE}'}))`;
        }

        javascriptGenerator.forBlock['try_catch'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const ARG = getValue(block, generator, 'ARG')
            let BODY0 = block.getInputTargetBlock('BODY0');
            let lines_0 = ''
            if (BODY0) {
                const line = generator.blockToCode(BODY0)
                lines_0 = (typeof line === 'string' ? line : line.join('\n'))
            }

            let BODY1 = block.getInputTargetBlock('BODY1');
            let lines_1 = ''
            if (BODY0) {
                const line = generator.blockToCode(BODY1)
                lines_1 = (typeof line === 'string' ? line : line.join('\n'))
            }
            return `try {\n${lines_0}\n} catch (${ARG}) {\n${lines_1}\n}`;
        }
    }
}